/*
 ============================================================================
 Name		: FbList.cpp
 Author	  : ceze
 Version	 :
 Copyright   : FlashBox for ver.Zhongyou(???)
 Description : CFbList implementation
 ============================================================================
 */

#include "FbList.h"

#include <EIKENV.H>
#include <stringloader.h>
#include "ConstDefined.hrh"
#include "Flashbox4.hrh"
#include "flashbox4.mbg"
#include "Flashbox4_0x20021B21.rsg"
#include "FbListData.h"

CFbList::CFbList (const TFbListStyle style ) :
	m_style (style )
{
	m_rgbText = KRgbBlack;
	m_rgbFocusedText = KRgbBlack;
	m_pageIndex = 0;
	m_indexFocused = 0;
//	m_textWidth = 0;
	m_textOffset = 0;
}

CFbList::~CFbList ()
{
	if(m_pPeriodic)
	{
		m_pPeriodic->Cancel();
		delete m_pPeriodic;
	}
	if (m_pListArray )
	{
		for (int i = 0; i < m_pListArray->Count (); i++ )
		{
			delete m_pListArray->At (i );
		}
		delete m_pListArray;
	}

	delete m_pBackImg;
	delete m_pFocusedBackImg;
	delete m_pDefaultIcon;
	iCoeEnv->ScreenDevice ()->ReleaseFont (m_pFont );
	//delete m_pScrollBar;

}

CFbList* CFbList::NewLC (const TRect &aRect, CCoeControl *pParent, const TFbListStyle style )
{
	CFbList* self = new (ELeave) CFbList (style );
	CleanupStack::PushL (self );
	self->ConstructL (aRect, pParent );
	return self;
}

CFbList* CFbList::NewL (const TRect &aRect, CCoeControl *pParent, const TFbListStyle style )
{
	CFbList* self = CFbList::NewLC (aRect, pParent, style );
	CleanupStack::Pop (); // self;
	return self;
}

void CFbList::ConstructL (const TRect &aRect, CCoeControl *pParent )
{
	//CreateWindowL (pParent );
	SetContainerWindowL(*pParent);
	m_pListArray = new (ELeave) CArrayPtrFlat<CFbListData> (12 );

	/*
	 //create scroll bar
	 m_pScrollBar = new (ELeave) CEikScrollBar;//
	 CleanupStack::PushL (m_pScrollBar );
	 m_pScrollBar->ConstructL (this, this, CEikScrollBar::EVertical, 0 );
	 TRect rect (aRect.iBr.iX - 6, aRect.iTl.iY + 1, aRect.iBr.iX - 1,
	 aRect.iBr.iY - 1 );
	 m_pScrollBar->SetRect (rect );
	 CleanupStack::Pop ();
	 */

	//calculate show arg
	TFontSpec fontSpec = iCoeEnv->NormalFont ()->FontSpecInTwips();
	//set font's size 80%
	fontSpec.iHeight = 7 * fontSpec.iHeight / 10;
	//apply font
	iCoeEnv->ScreenDevice ()->GetNearestFontInTwips (m_pFont, fontSpec );
	TInt fontHeight = m_pFont->HeightInPixels ();
	
	if(m_style != EStyleOptionMenu)
	{
		m_maxItemsShow = (aRect.Height () - 4) / (fontHeight + 4)  - 1;
		m_pDefaultIcon = (CEikonEnv::Static ())->CreateBitmapL (KFlashboxImagePath, EMbmFlashbox4Applogo );
		m_pPeriodic = CPeriodic::NewL(CActive::EPriorityIdle);
		m_pPeriodic->Start(100000,100000,TCallBack(CFbList::DrawCallback,this));
	}
	m_initRect = aRect;
	SetRect (m_initRect);
}

/**
 * 添加列表项
 * aIndex加入位置, 默认添加到最后
 */
void CFbList::AddItemL (CFbListData *pItemData, const TInt aIndex )
{
	if (m_pListArray == NULL )
		m_pListArray = new (ELeave) CArrayPtrFlat<CFbListData> (12 );
	
	if (aIndex < 0 || aIndex >= m_pListArray->Count () )
	{
		//append
		m_pListArray->AppendL (pItemData );
	}
	else
	{
		//插入到某一位置
		m_pListArray->InsertL (aIndex, pItemData );
	}
	
	if(m_style == EStyleOptionMenu)
	{
		//重新计算区域大小
		TInt itemCount = m_pListArray->Count();
		TInt rectHeight = itemCount * (m_pFont->HeightInPixels () + 5) + 2;
		TRect origRect(m_initRect);
		TInt dH = rectHeight - origRect.Height();
		m_initRect.SetRect(origRect.iTl.iX, origRect.iTl.iY - dH, origRect.iBr.iX, origRect.iBr.iY);
		m_maxItemsShow = itemCount;
		SetRect(m_initRect);	
	}
}

/**
 * 删除指定列表项
 */
void CFbList::RemoveItem (const TInt aIndex )
{
	
	if (m_pListArray == NULL || aIndex < 0 || aIndex >= m_pListArray->Count () )
	{
		return;
	}
	else
	{
		CFbListData *pTemp = static_cast<CFbListData*> (m_pListArray->At (aIndex ) );
		m_pListArray->Delete (aIndex );
		delete pTemp;
		pTemp = NULL;
		m_pListArray->Compress ();
	}
	
	if(m_style == EStyleOptionMenu)
	{
		//重新计算区域大小
		TInt itemCount = m_pListArray->Count ();
		TInt rectHeight = itemCount * (m_pFont->HeightInPixels () + 5) + 2;
		TRect origRect (m_initRect );
		TInt dH = rectHeight - origRect.Height ();
		m_initRect.SetRect (origRect.iTl.iX, origRect.iTl.iY - dH,
				origRect.iBr.iX, origRect.iBr.iY );
		m_maxItemsShow = itemCount;
		SetRect (m_initRect );
	}
	DrawNow();
}

/**
 * 删除所有列表项
 */
void CFbList::RemoveAll ()
{
	if (m_pListArray )
	{
		for (int i = 0; i < m_pListArray->Count (); i++ )
		{
			delete m_pListArray->At (i );
		}
		m_pListArray->Reset ();
	}
	m_indexFocused = 0;
	m_pageIndex = 0;
	//m_textWidth = 0;
	m_textOffset = 0;
	DrawNow();
}

/**
 * List
 */
void CFbList::SetBackground (const TRgb &aFrameRgb, const TRgb &aBackRgb, const TInt &aResId )
{
	m_rgbFrame = aFrameRgb;
	m_rgbBack = aBackRgb;
	if (aResId > 0 )
		m_pBackImg = (CEikonEnv::Static ())->CreateBitmapL (KFlashboxImagePath,
				aResId );
}

/**
 * focused background
 */
void CFbList::SetFocusedBackground (const TRgb &aRgb, const TInt &aResId )
{
	m_rgbFocusedBack = aRgb;
	if (aResId > 0 )
		m_pFocusedBackImg = (CEikonEnv::Static ())->CreateBitmapL (
				KFlashboxImagePath, aResId );
}

/**
 * From CoeControl,SizeChanged.
 */
void CFbList::SizeChanged ()
{
	DrawNow ();
}

/**
 * From CoeControl,CountComponentControls.
 */
TInt CFbList::CountComponentControls () const
{
	return 0;
}

/**
 * From CCoeControl,ComponentControl.
 */
CCoeControl* CFbList::ComponentControl (TInt aIndex ) const
{
	switch (aIndex )
	{
	case 0:
		return NULL;//m_pScrollBar;
	default:
		return NULL;
	}
}

/*
 * From CoeControl,
 * 按键事件接收处理
 */
TKeyResponse CFbList::OfferKeyEventL (const TKeyEvent &aKeyEvent, TEventCode aType )
{
	TInt code = EKeyDevice3;
	TInt maxCount;
	//maxCount = m_pListArray->Count () > m_maxItemsShow ?
	//				m_maxItemsShow : m_pListArray->Count ();
	TInt oddCount = m_pListArray->Count () % m_maxItemsShow;
	TInt totalPage = m_pListArray->Count () / m_maxItemsShow;
	if(m_pageIndex >= totalPage)
	{
		maxCount = oddCount == 0 ? m_maxItemsShow : oddCount;
	}
	else
	{
		maxCount = m_maxItemsShow;
	}
	
	TInt origIndex = m_indexFocused;
	switch (aKeyEvent.iCode )
	{
	case EKeyUpArrow:
		m_indexFocused--;
		m_indexFocused = m_indexFocused < 0 ? maxCount - 1 : m_indexFocused;
		DrawNow ();
		break;
	case EKeyDownArrow:
		m_indexFocused++;
		m_indexFocused = m_indexFocused >=  maxCount ? 
				0 : m_indexFocused;
		DrawNow ();
		break;
	case EKeyDevice3:
		if (m_pObserver )
		{
			TInt itemId = -1;
			TInt indexInArray = m_pageIndex * m_maxItemsShow + m_indexFocused;
			CFbListData *pData = this->GetListItem(indexInArray);
			if(pData)
			{
				itemId = pData->GetItemId();
			}
			m_pObserver->ListItemEvent (this, indexInArray, itemId, EItemSelected );
		}
		break;
	default:
		if (m_style == EStyleOptionMenu )
		{
			return EKeyWasConsumed;
		}
		else
		{
			return EKeyWasNotConsumed;
		}
	}
	if(m_style == EStyleDataList && origIndex != m_indexFocused)
	{
		m_textOffset = 0;
	}
	
	return EKeyWasConsumed;
}

/**
 * From CCoeControl,Draw.
 */
void CFbList::Draw (const TRect& aRect ) const
{
	// Get the standard graphics context
	CWindowGc& gc = SystemGc ();
	TRect drawRect (Rect () );
	gc.SetPenStyle (CGraphicsContext::ESolidPen );
	gc.SetBrushStyle (CGraphicsContext::ESolidBrush );
	gc.SetBrushColor (m_rgbBack );
	gc.SetPenColor(KRgbBlack);
	gc.DrawRect (TRect(TPoint(drawRect.iTl.iX + 1 , drawRect.iTl.iY + 1), drawRect.Size()));
	gc.SetPenColor (m_rgbFrame );
	gc.DrawRect (drawRect );

	//画背景图
	if (m_pBackImg )
		gc.DrawBitmap (drawRect, m_pBackImg );
	
	//draw item
	if (m_pListArray )
	{
		TInt itemCount = m_pListArray->Count ();
		if (itemCount <= 0 )
			return;
		//font
		//const CFont *pFont = iCoeEnv->NormalFont ();
		TInt fontHeight = m_pFont->HeightInPixels ();
		gc.UseFont (m_pFont );
		//位置偏移
		//
		//item draw pos
		TPoint itemPos (drawRect.iTl.iX, drawRect.iTl.iY + 1 );
		TInt showIndexInArray = m_pageIndex * m_maxItemsShow;
		for (TInt i = 0; i  < itemCount - showIndexInArray && i < m_maxItemsShow ; i++ )
		{
		//	if(i >= m_pageItemsShow)
		//		break;
			
			TPoint textPos (itemPos.iX + 1, itemPos.iY + fontHeight + 1 );
			CFbListData * pItem = m_pListArray->At (i + showIndexInArray );
			
			if (i == m_indexFocused )//焦点所在,需展开
			{
				//画焦点所在背景区域
				if(i > 0)
				{
					itemPos.iY += 1; //出现挪动效果
					textPos.iY += 2;
				}
				
				textPos.iY += 3;
				
				TRect focusedRect;
				if (m_pFocusedBackImg )
				{
					//background size
					TSize focusedSize = m_pFocusedBackImg->SizeInPixels ();
					focusedRect.SetRect (itemPos, focusedSize );
					//
					gc.DrawBitmap (focusedRect, m_pFocusedBackImg );
				}
				else//不包含图
				{
					//背景区域
					if (m_style == EStyleOptionMenu )//option菜单
					{
						focusedRect.SetRect (itemPos.iX+1, itemPos.iY,
								drawRect.iBr.iX-1, itemPos.iY + (fontHeight
										+ 2) );
					}
					else //普通list
					{
						focusedRect.SetRect (itemPos.iX, itemPos.iY,
								drawRect.iBr.iX - 2, itemPos.iY + (fontHeight
										+ 5) * 2 );
					}
					gc.SetPenColor (m_rgbFocusedBack );
					gc.SetBrushColor (m_rgbFocusedBack );
					gc.SetBrushStyle(CGraphicsContext::ESolidBrush);
					gc.SetPenStyle(CGraphicsContext::ENullPen);
					gc.DrawRect (focusedRect );
				}
				
				//文字
				if (m_style == EStyleDataList )
				{	
					//画大图标
					CFbsBitmap *pLargeIcon = m_pDefaultIcon;//pItem->m_pLargeIcon;;
					if(pItem->m_pMulImage && pItem->m_pMulImage->GetBitmap())
					{
						pLargeIcon =  pItem->m_pMulImage->GetBitmap();
					}
					
					if (pLargeIcon)
					{
						TSize iconSize (pLargeIcon->SizeInPixels () );
						if (iconSize.iHeight > focusedRect.Height () )
						{
							iconSize.SetSize (focusedRect.Height (),
									focusedRect.Height () );
						}
						TRect iconRect (TPoint (itemPos.iX, itemPos.iY
								+ (focusedRect.Height () - iconSize.iHeight)
										/ 2 ), iconSize );
						gc.DrawBitmap (iconRect, pLargeIcon);
						textPos.iX += iconRect.Width ();
					}
					//写文字
					textPos.iX += 2;
					textPos.iY += 2;
					gc.SetPenColor (m_rgbFocusedText );
					gc.SetPenStyle(CGraphicsContext::ESolidPen);
					if (pItem->GetTitle () )
					{
						gc.DrawText (*pItem->GetTitle (), textPos );
					}
					textPos.iY += (fontHeight + 3);
					if (pItem->GetDescript () )
					{
						//gc.SetPenStyle(CGraphicsContext::EDotDotDashPen);
						gc.SetClippingRect(TRect(textPos.iX, focusedRect.iTl.iY, focusedRect.iBr.iX, focusedRect.iBr.iY));
						gc.DrawText (*pItem->GetDescript (), TPoint(textPos.iX - m_textOffset, textPos.iY));
						gc.CancelClippingRect();
						
					}
				}
				else//EStyleOptionMenu样式
				{
					//写文字
					gc.SetPenColor (m_rgbFocusedText );
					gc.SetPenStyle(CGraphicsContext::ESolidPen);
					if (pItem->GetTitle () )
					{
						gc.SetBrushStyle(CGraphicsContext::ENullBrush);
						gc.DrawText (*pItem->GetTitle (), focusedRect, fontHeight, CGraphicsContext::ECenter);
					}
				}	
				//画横线
				gc.SetPenColor(0xbbbbbb);
				gc.SetPenStyle(CGraphicsContext::EDashedPen);
				gc.DrawLine(TPoint(drawRect.iTl.iX, textPos.iY + 2), TPoint(drawRect.iBr.iX - 6, textPos.iY + 2));

				//位置下移
				itemPos.iY += focusedRect.Height () + 4;
			}
			else//非焦点
			{
				//出现挪动效果
				if(i == m_indexFocused + 1)
				{
					textPos.iY += 1;
				}
				if(i == m_indexFocused - 1)
				{
					textPos.iY -= 1;
				}
				
				//画小标
				if (pItem->m_pSmallIcon )
				{
					TSize iconSize (pItem->m_pSmallIcon->SizeInPixels () );
					if (iconSize.iHeight > fontHeight + 1 )
					{
						iconSize.SetSize (fontHeight + 1, fontHeight + 1 );
					}
					TRect iconRect (TPoint (itemPos.iX + 1, itemPos.iY
							+ (fontHeight - iconSize.iHeight) / 2 ), iconSize );
					gc.DrawBitmap (iconRect, pItem->m_pSmallIcon );
					textPos.iX += iconRect.Width ();
				}
				gc.SetPenColor (m_rgbText );
				gc.SetPenStyle(CGraphicsContext::ESolidPen);
				if (pItem->GetTitle () )
				{
					if(m_style == EStyleDataList)
					{
						textPos.iX += 2;
						gc.DrawText (*pItem->GetTitle (), textPos );
					}
					else//EStyleOptionMenu样式
					{
						gc.SetBrushStyle(CGraphicsContext::ENullBrush);
						TRect textRect(itemPos.iX, itemPos.iY, 
								drawRect.iBr.iX -2,  itemPos.iY + fontHeight);
						gc.DrawText (*pItem->GetTitle (), textRect, fontHeight, CGraphicsContext::ECenter);
					}
					//画横线
					gc.SetPenColor(0xbbbbbb);
					gc.SetPenStyle(CGraphicsContext::EDashedPen);
					gc.DrawLine(TPoint(drawRect.iTl.iX, textPos.iY + 1), TPoint(drawRect.iBr.iX - 6, textPos.iY + 1));
				}
				//offset pos y
				itemPos.iY += (fontHeight + 4);
			}
		}
		gc.DiscardFont ();
	}
}

/**
 * 通过itemIndex获取列表项
 */
CFbListData * CFbList::GetListItem (const TInt itemIndex )
{
	if (m_pListArray == NULL || itemIndex < 0 || itemIndex
			>= m_pListArray->Count () )
		return NULL;
	else
		return m_pListArray->At (itemIndex );
}

/**
 * 获取焦点所在位置
 */
TInt CFbList::GetFocusedIndex ()
{
	//焦点在全局数组中的位置
	return m_pageIndex * m_maxItemsShow + m_indexFocused;
}

void CFbList::SetTextColor (const TRgb &aTextRgb, const TRgb &aFocusedTextRgb )
{
	m_rgbText = aTextRgb;
	m_rgbFocusedText = aFocusedTextRgb;
}

/**
 * next page
 */
/*
void CFbList::NextPage ()
{
	if (m_pListArray == NULL )
		return;
	TInt pageCount = m_pListArray->Count () / m_maxItemsShow;
	if (m_pListArray->Count () % m_maxItemsShow > 0 )
	{
		pageCount += 1;
	}

	m_pageIndex++;
	
	if (m_pageIndex >= pageCount )
	{
		m_pageIndex = pageCount - 1;
	}
}
*/
/**
 * Prev page
 */
/*
void CFbList::Prevpage ()
{
	m_pageIndex--;
	if (m_pageIndex < 0 )
		m_pageIndex = 0;
}
*/

/**
 * 
 */
TInt CFbList::CurrentPageIndex ()
{
	return m_pageIndex;
}

/**
 * 设置消息监听接口
 */
void CFbList::SetObserver (MListObserver *pObserver )
{
	m_pObserver = pObserver;
}

/**
 * from CCoeControl
 */

void CFbList::MakeVisible (TBool aVisible )
{
	CCoeControl::MakeVisible (aVisible );

	if (!m_pObserver )
		return;
	
	if (aVisible )
		m_pObserver->ListItemEvent (this, -1, -1, EMakeVisibleTrue );
	else
		m_pObserver->ListItemEvent (this, -1, -1, EMakeVisibleFalse );
}

/**
* Next Page
 */
void CFbList::NextListPage ()
{
	TInt totalPage = m_pListArray->Count () / m_maxItemsShow;
			if (m_pListArray->Count () % m_maxItemsShow > 0)
				totalPage += 1;
	if(m_maxItemsShow >= m_pListArray->Count ())
	{
		m_pObserver->ListItemEvent(this, 1, 1, EPageSingl);
	}
	else if((m_pageIndex + 1) * m_maxItemsShow < m_pListArray->Count ())
	{
		m_pageIndex++;
		m_indexFocused = 0;
		if((m_pageIndex + 1) * m_maxItemsShow >= m_pListArray->Count ())
		{
			m_pObserver->ListItemEvent(this, m_pageIndex+1, totalPage, EPageMultLast);
		}
		else
		{
			m_pObserver->ListItemEvent(this, m_pageIndex+1, totalPage, EPageMultMiddle);
		}
	}
	else
	{
		m_pObserver->ListItemEvent(this, m_pageIndex+1, totalPage, EPageMultLast);
	}
	DrawNow();
}

/**
 * Prev page
 */
void CFbList::PrevListPage()
{
	
	if(m_maxItemsShow >= m_pListArray->Count ())
	{
		m_pObserver->ListItemEvent(this, 1, 1, EPageSingl);
	}
	else
	{
		TInt totalPage = m_pListArray->Count () / m_maxItemsShow;
		if (m_pListArray->Count () % m_maxItemsShow > 0)
				totalPage += 1;
		if(m_pageIndex > 0)
		{
			m_pageIndex--;
			m_indexFocused = 0;
		}
		if(m_pageIndex == 0)
		{
			m_pObserver->ListItemEvent(this, m_pageIndex+1, totalPage, EPageMultFirst);
		}
		else
		{
			m_pObserver->ListItemEvent(this, m_pageIndex+1, totalPage, EPageMultMiddle);
		}
	}
	DrawNow();
	
}

/*
	 * 更新(获取)页面显示状态
 */
void CFbList::UpdatePageSatuse ()
{
	if(m_maxItemsShow >= m_pListArray->Count ())
	{
		m_pObserver->ListItemEvent(this, 1, 1, EPageSingl);
	}
	else
	{
		TInt totalPage = m_pListArray->Count () / m_maxItemsShow;
		if (m_pListArray->Count () % m_maxItemsShow > 0)
			totalPage += 1;
		
		if(m_pageIndex == 0)
		{
			m_pObserver->ListItemEvent(this, m_pageIndex + 1, totalPage, EPageMultFirst);
		}
		else if((m_pageIndex + 1) * m_maxItemsShow >= m_pListArray->Count ())
		{
			m_pObserver->ListItemEvent(this, m_pageIndex + 1, totalPage, EPageMultLast);
		}
		else
		{
			m_pObserver->ListItemEvent(this, m_pageIndex + 1, totalPage, EPageMultMiddle);
		}
	}
}


/**
 * 判断传入的项id是否存在
 * 返回值,-1不存在, 其它所在位置序号
 */
TInt CFbList::IndexByItmeId (const TInt itemId )
{
	for(TInt i = 0; i < m_pListArray->Count(); i++)
	{
		CFbListData *pData= m_pListArray->At(i);
		if(pData->GetItemId() == itemId)
			return i;
	}
	
	return -1;
}

/**
 * 刷屏回调函数
 */
TInt CFbList::DrawCallback (TAny* pInst )
{
	CFbList *pFbList = (CFbList*)pInst;
	if(!pFbList->IsVisible())
		return KErrNone;
	
	pFbList->m_textOffset += 3;
	TInt indexInArray = pFbList->m_pageIndex * pFbList->m_maxItemsShow + pFbList->m_indexFocused;
	CFbListData *pData = pFbList->GetListItem (indexInArray );
	TInt textWidth = 0;
	if (pData && pData->GetDescript() )
	{
		textWidth = pFbList->m_pFont->TextWidthInPixels (
				pData->GetDescript()->Des () );
	}	
	if(pFbList->m_textOffset >= textWidth - pFbList->Rect().Width() + 80)
	{
		pFbList->m_textOffset = -30;
	}
	pFbList->DrawNow();
	return KErrNone;
}

TInt CFbList::GetFocusItemPosY()
{
	TInt tmpPosY = 0;
	tmpPosY = Rect().iTl.iY + 1;
	if(GetFocusedIndex() <= 7)
	{
		tmpPosY += (m_pFont->HeightInPixels() + 2) * GetFocusedIndex();
		if (m_pFocusedBackImg)
			tmpPosY += m_pFocusedBackImg->SizeInPixels().iHeight;
		else
			tmpPosY += (m_pFont->HeightInPixels() + 5) * 2;
	}
	else
	{
		tmpPosY += (m_pFont->HeightInPixels() + 2) * (GetFocusedIndex() - 1);
		tmpPosY -= (m_pFont->HeightInPixels() + 5) * 2;
	}
	
	return tmpPosY;
}

/**
 * from MEikScrollBarObserver
 */
//void CFbList::HandleScrollEventL (CEikScrollBar * aScrollBar, TEikScrollEvent aEventType )
//{
//	
//}

